package rs.udd.web.config;

import java.util.List;
import java.util.Properties;

import javax.servlet.ServletContext;

import org.apache.lucene.search.BooleanClause.Occur;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import rs.udd.constants.GeneralConstants.SearchType;
import rs.udd.model.Advertiser.AdvertiserType;
import rs.udd.model.Agent.Gender;
import rs.udd.model.Role.Roles;

@Configuration
@ComponentScan({ "rs.udd" })
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true)
// @EnableGlobalMethodSecurity annotation is placed in this class because of multiple contexts exist, and web mvc context sees security contxt,
// and we want to secure methods from web mvc context (i.e. controller methods etc.)
@PropertySources({ @PropertySource("classpath:database.properties"), @PropertySource("classpath:application.properties") })
public class UddWebAppSpringConfiguration extends WebMvcConfigurerAdapter implements ServletContextAware {

	@Autowired
	private Environment env;

	private static final String VIEW_RESOLVER_PREFIX = "view.resolver.prefix";
	private static final String VIEW_RESOLVER_SUFFIX = "view.resolver.sufix";

	private static final String MESSAGE_PROPERTIES_FILE_NAME = "message.properties.file.name";

	private static final String MAIL_HOST = "mail.host";
	private static final String MAIL_PORT = "mail.port";
	private static final String MAIL_USERNAME = "mail.username";
	private static final String MAIL_PASSWORD = "mail.password";
	private static final String MAIL_SUBJECT = "mail.subject";

	private static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";
	private static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
	private static final String MAIL_SMTP_STARTTLS = "mail.smtp.starttls.enable";

	@Override
	public void setServletContext(ServletContext servletContext) {

		servletContext.setAttribute("advertiserTypes", AdvertiserType.values());
		servletContext.setAttribute("genders", Gender.values());

		servletContext.setAttribute("adminRole", Roles.ADMIN.name());
		servletContext.setAttribute("advertiserRole", Roles.ADVERTISER.name());
		servletContext.setAttribute("agentRole", Roles.AGENT.name());
		
		servletContext.setAttribute("searchTypes", SearchType.values());
		servletContext.setAttribute("occures", Occur.values());
	}

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {

		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
		registry.addResourceHandler("/css/**").addResourceLocations("/css/");
		registry.addResourceHandler("/images/**").addResourceLocations("/images/");
		registry.addResourceHandler("/js/**").addResourceLocations("/js/");
		registry.addResourceHandler("/fonts/**").addResourceLocations("/fonts/");
	}
	
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		converters.add(new MappingJackson2HttpMessageConverter());
	}
	
	@Bean
	public MessageSource messageSource() {

		ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();

		resourceBundleMessageSource.setBasename(env.getProperty(MESSAGE_PROPERTIES_FILE_NAME));

		return resourceBundleMessageSource;
	}

	@Bean
	public InternalResourceViewResolver internalResourceViewResolver() {

		InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();

		internalResourceViewResolver.setPrefix(env.getProperty(VIEW_RESOLVER_PREFIX));
		internalResourceViewResolver.setSuffix(env.getProperty(VIEW_RESOLVER_SUFFIX));
		internalResourceViewResolver.setViewClass(JstlView.class);

		return internalResourceViewResolver;
	}

	@Bean
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

		return new PropertySourcesPlaceholderConfigurer();
	}

	@Bean
	public JavaMailSender mailSender() {

		JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();

		javaMailSender.setHost(env.getProperty(MAIL_HOST));
		javaMailSender.setPort(Integer.parseInt(env.getProperty(MAIL_PORT)));
		javaMailSender.setUsername(env.getProperty(MAIL_USERNAME));
		javaMailSender.setPassword(env.getProperty(MAIL_PASSWORD));
		javaMailSender.setJavaMailProperties(javaMailProperties());

		return javaMailSender;
	}

	private Properties javaMailProperties() {

		Properties javaMailProperties = new Properties();

		javaMailProperties.setProperty(MAIL_TRANSPORT_PROTOCOL, env.getProperty(MAIL_TRANSPORT_PROTOCOL));
		javaMailProperties.setProperty(MAIL_SMTP_AUTH, env.getProperty(MAIL_SMTP_AUTH));
		javaMailProperties.setProperty(MAIL_SMTP_STARTTLS, env.getProperty(MAIL_SMTP_STARTTLS));

		return javaMailProperties;
	}

	@Bean
	public SimpleMailMessage simpleMailMessage() {

		SimpleMailMessage simpleMailMessage = new SimpleMailMessage();

		simpleMailMessage.setFrom(env.getProperty(MAIL_USERNAME));
		simpleMailMessage.setSubject(env.getProperty(MAIL_SUBJECT));

		return simpleMailMessage;
	}

	@Bean
	public CommonsMultipartResolver multipartResolver() {

		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();

		return multipartResolver;
	}
}
